﻿using System.Windows;
using System.Windows.Input;

namespace VisualWip.PresentationModel
{
    public static class MouseBehavior
    {
        public static DependencyProperty RightClickCommandProperty = DependencyProperty.RegisterAttached(
            "RightClick", typeof (ICommand), typeof (MouseBehavior),
            new FrameworkPropertyMetadata(null, new PropertyChangedCallback(RightClickChanged)));

        public static DependencyProperty DoubleClickCommandProperty = DependencyProperty.RegisterAttached(
            "DoubleClick", typeof (ICommand), typeof (MouseBehavior),
            new FrameworkPropertyMetadata(null, new PropertyChangedCallback(DoubleClickChanged)));

        public static DependencyProperty MoveCommandProperty = DependencyProperty.RegisterAttached(
            "Move", typeof (ICommand), typeof (MouseBehavior),
            new FrameworkPropertyMetadata(null, new PropertyChangedCallback(MoveChanged)));

        private static void MoveChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            var element = target as UIElement;
            if (element != null)
            {
                // If we're putting in a new command and there wasn't one already
                // hook the event
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    element.PreviewMouseMove += element_PreviewMouseMove;
                }
                    // If we're clearing the command and it wasn't already null
                    // unhook the event
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    element.PreviewMouseMove -= element_PreviewMouseMove;
                }
            }
        }

        private static void element_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                var element = (UIElement) sender;
                var command = (ICommand) element.GetValue(MoveCommandProperty);
                command.Execute(sender);
            }
        }

        public static void SetMove(DependencyObject target, ICommand value)
        {
            target.SetValue(MoveCommandProperty, value);
        }

        public static ICommand GetMove(DependencyObject target)
        {
            return (ICommand) target.GetValue(MoveCommandProperty);
        }

        public static void SetRightClick(DependencyObject target, ICommand value)
        {
            target.SetValue(RightClickCommandProperty, value);
        }

        public static ICommand GetRightClick(DependencyObject target)
        {
            return (ICommand) target.GetValue(RightClickCommandProperty);
        }

        public static void SetDoubleClick(DependencyObject target, ICommand value)
        {
            target.SetValue(DoubleClickCommandProperty, value);
        }

        public static ICommand GetDoubleClick(DependencyObject target)
        {
            return (ICommand) target.GetValue(DoubleClickCommandProperty);
        }

        private static void RightClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            var element = target as UIElement;
            if (element != null)
            {
                // If we're putting in a new command and there wasn't one already
                // hook the event
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    element.MouseRightButtonUp += element_MouseRightButtonUp;
                }
                    // If we're clearing the command and it wasn't already null
                    // unhook the event
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    element.MouseRightButtonUp -= element_MouseRightButtonUp;
                }
            }
        }

        private static void DoubleClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            var element = target as UIElement;
            if (element != null)
            {
                // If we're putting in a new command and there wasn't one already
                // hook the event
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    element.MouseDown += element_MouseDown;
                }
                    // If we're clearing the command and it wasn't already null
                    // unhook the event
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    element.MouseDown -= element_MouseDown;
                }
            }
        }

        private static void element_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                var element = (UIElement) sender;
                var command = (ICommand) element.GetValue(DoubleClickCommandProperty);
                command.Execute(null);
            }
        }


        private static void element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            var element = (UIElement) sender;
            var command = (ICommand) element.GetValue(RightClickCommandProperty);
            command.Execute(null);
        }
    }
}